<?php

namespace App\Kuafu\Coupon\Service;

use App\Kuafu\Activity\Enum\ActivityEnum;
use App\Kuafu\Activity\Model\ActivityCouponMappingModel;
use App\Kuafu\Activity\Model\ActivityModel;
use App\Kuafu\Activity\Service\ActivityService;
use App\Kuafu\Base\Util\DateTimeUtil;
use App\Kuafu\Coupon\Enum\CouponCodeEnum;
use App\Kuafu\Coupon\Enum\CouponEnum;
use App\Kuafu\Coupon\Model\CouponModel;
use App\Kuafu\Coupon\Exceptions\CouponException;
use App\Kuafu\Base\Service\BaseService;
use App\Kuafu\CouponExt\Channel\CouponExtBase;
use App\Kuafu\CouponExt\Enum\CouponExtCodeEnum;
use App\Kuafu\CouponExt\Enum\CouponExtEnum;
use App\Kuafu\CouponExt\Exceptions\CouponExtException;
use App\Kuafu\Product\Model\Product;
use App\Kuafu\Product\Service\ProductService;
use App\Kuafu\Shop\Service\ShopService;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;

class CouponService extends BaseService
{
    public static function getCouponById(int $id): array
    {
        $couponDetail = CouponModel::query()->find($id)->toArray();
        if (!$couponDetail) {
            return [];
        }
        $couponDetail['availableSourceText'] = self::availableSourceRules($couponDetail['availableSource']);
        //查询优惠券关联商品信息
        $productName = [];
        if ($couponDetail['canUseProduct']) {
            $field       = ['id', 'name'];
            $byIds       = ProductService::getListByIds(explode(',', $couponDetail['canUseProduct']), $field, 0);
            $productName = array_column($byIds->toArray(), 'name');
        }
        if ($couponDetail['type'] == CouponEnum::COUPON_TYPE_VOUCHERS) {
            $couponDetail['typeDesc'] = '￥' . $couponDetail['discount'] / 100;
        } elseif ($couponDetail['type'] == CouponEnum::COUPON_TYPE_DISCOUNT) {
            $couponDetail['typeDesc'] = $couponDetail['discount'] / 10 . '折';
        }
        $couponDetail["couponImg"]   = picturePath($couponDetail["couponImg"]);
        $couponDetail['productList'] = $productName;

        $couponDetail['unableTime'] = json_decode(
            empty($couponDetail['unableTime']) ? "[]" : $couponDetail['unableTime'],
            true
        );
        return $couponDetail;
    }

    /**
     * 获取优惠券列表
     * @param $startAt
     * @param $name
     * @param $type
     * @param $channel
     * @param $status
     * @param $pageSize
     * @param $pageNum
     * @param bool $filter 过滤已经占用的优惠券
     * @return array
     */
    public static function getCouponList(
        $startAt,
        $name,
        $type,
        $channel,
        $status,
        $pageSize,
        $pageNum,
        bool $filter = false,
        $source = ''
    ): array {
        $paginator      = CouponModel::getDataPage($startAt, $name, $type, $channel, $status, $pageSize, $pageNum,
            $source);
        $boundCouponIds = [];
        if ($filter) {
            // 查询已经绑定的优惠券id数组
            $boundCouponIds = ActivityCouponMappingModel::query()
                                                        ->selectRaw('distinct(`couponId`) as couponId')
                                                        ->pluck('couponId')
                                                        ->toArray();
        }
        $queryList = $paginator->map(function (CouponModel $couponModel) use ($boundCouponIds) {
            if (in_array($couponModel->id, $boundCouponIds)) {
                return null;
            }
            $item = $couponModel->toArray();
            if ($item['type'] == CouponEnum::COUPON_TYPE_VOUCHERS) {
                $item['typeDesc'] = '￥' . $item['discount'] / 100;
            } elseif ($item['type'] == CouponEnum::COUPON_TYPE_DISCOUNT) {
                $item['typeDesc'] = $item['discount'] / 10 . '折';
            }
            $item['availableSourceText'] = self::availableSourceRules($item['availableSource']);
            return $item;
        })->filter()->toArray();
        $count     = $paginator->total();
        if ($filter) {
            $count = count($queryList);
        }
        return [
            'pageNum'   => $paginator->currentPage(),
            'pageSize'  => $paginator->perPage(),
            'pageCount' => $paginator->lastPage(),
            'count'     => $count,
            'lists'     => array_values($queryList),
        ];
    }

    /**
     * 可使用渠道算法
     * @param int $total
     * @return string
     */
    public static function availableSourceRules(int $total): string
    {
        //全部渠道不需要判断
        if ($total == CouponEnum::SOURCE_ALL) {
            return CouponEnum::PUBLICCHANNELS[$total];
        }

        $source    = CouponEnum::AVAILABLESOURCE;
        $channels  = '';
        $available = array_keys($source);

        //保证数组必须降序排列
        rsort($available);

        foreach ($available as $totalItem) {

            if ($totalItem > $total) {
                continue;
            }
            $total    -= $totalItem;
            $channels .= CouponEnum::AVAILABLESOURCE[$totalItem] . ",";

        }
        return rtrim($channels, ',');
    }

    public static function addCoupon(array $data): CouponModel
    {
        $coupon                 = new CouponModel;
        $coupon->name           = mb_substr($data['name'], 0, 50);
        $coupon->desc           = $data['desc'] ?? "";
        $coupon->type           = $data['type'];
        $coupon->costPrice      = $data['costPrice'] ?: 0;
        $coupon->productUseType = isset($data['productUseType']) ? 1 : 0;
        //处理优惠券类型
        $useCondition = $data['useCondition'] ?? 0;
        $discount     = $data['discount'] ?? 0;
        switch ($data['type']) {
            case CouponEnum::COUPON_TYPE_VOUCHERS:
                // 代金券
                if ($useCondition > 0 && $discount > $useCondition) {
                    throw new CouponException(CouponCodeEnum::ERR_COUPON_PARAM_VALID, '优惠金额不能大于使用门槛');
                }
                break;
            case CouponEnum::COUPON_TYPE_DISCOUNT:
                if ($discount < 1 || $discount > 99) {
                    throw new CouponException(CouponCodeEnum::ERR_COUPON_PARAM_VALID, '折扣范围为1~99');
                }
                break;
            case CouponEnum::COUPON_TYPE_EXCHANGE:
                break;
            default :
                throw new CouponException(CouponCodeEnum::ERR_COUPON_PARAM_VALID, '折扣类型错误');
        }
        $coupon->discount        = $discount;
        $coupon->useCondition    = $useCondition;
        $coupon->isExpireNotice  = $data['isExpireNotice'] ?? 0;
        $coupon->isArrivalNotice = $data['isArrivalNotice'] ?? 0;
        $coupon->expireNoticeDay = $data['expireNoticeDay'] ?? 0;
        $coupon->couponImg       = isset($data["couponImg"]) ? getPicturePath($data["couponImg"]) : "";
        if ($data['canUseProduct'] != 0) {
            $productExistIds = array_unique(Product::query()
                                                   ->whereIn('id', explode(',', $data['canUseProduct'] ?? ''))
                                                   ->where('menuId', 0)
                                                   ->pluck('id')
                                                   ->toArray());
            if (!count($productExistIds)) {
                throw new CouponException(CouponCodeEnum::ERR_COUPON_PRODUCT_NOT_EXIST, '兑换的商品不存在');
            }
            $coupon->canUseProduct = implode(',', $productExistIds);
        }
        // 时间
        $coupon->useTimeType = $data['useTimeType'];
        switch ($coupon->useTimeType) {
            case CouponEnum::TIME_TYPE_ABSOLUTE:
                $coupon->startAt = strtotime($data['startAt']);
                $coupon->endAt   = strtotime($data['endAt']);
                break;
            case CouponEnum::TIME_TYPE_RELATIVE:
                // 领取后第$data['startAt']天后可以使用，有效$data['endAt']天数
                if ($data['startAt'] < 0) {
                    throw new CouponException(CouponCodeEnum::ERR_COUPON_PARAM_VALID, '有效期开始天数至少为0天');
                }
                if ($data['endAt'] < 1) {
                    throw new CouponException(CouponCodeEnum::ERR_COUPON_PARAM_VALID, '有效期有线天数至少为1天');
                }
                $coupon->startAt = $data['startAt'];
                $coupon->endAt   = $data['endAt'];
                break;
        }
        $coupon->useCondition        = $data['useCondition'];
        $coupon->useMax              = $data['useMax'] ?? 1;
        $coupon->cappedAmount        = $data['cappedAmount'] ?? 0;
        $coupon->availableSource     = collect($data['availableSource'])->sum();
        $coupon->isSuperposeCoupon   = $data['isSuperposeCoupon'] ?? 0;
        $coupon->isSuperposeActivity = $data['isSuperposeActivity'] ?? 0;
        $coupon->unableDate          = collect($data['unableDate'])->implode(",");
        foreach ($data['unableTime'] as &$item) {
            if (!isset($item['startAt']) || !isset($item['endAt'])) {
                throw new CouponException(CouponCodeEnum::ERR_COUPON_PARAM_VALID, '不可用时间格式不正确');
            }
            $item['startAt'] = DateTimeUtil::clockToSeconds($item['startAt']);
            $item['endAt']   = DateTimeUtil::clockToSeconds($item['endAt']);
            if (null === $item['startAt'] || $item['startAt'] < 0) {
                throw new CouponException(CouponCodeEnum::ERR_COUPON_PARAM_VALID, '不可用时间不能早于00:00');
            }
            if (null === $item['endAt'] || $item['endAt'] >= 86400) {
                throw new CouponException(CouponCodeEnum::ERR_COUPON_PARAM_VALID, '不可用时间不能晚于23:59');
            }
            if ($item['startAt'] > $item['endAt']) {
                throw new CouponException(CouponCodeEnum::ERR_COUPON_PARAM_VALID, '不可用时间起始时间不能晚于结束时间');
            }
        }
        $coupon->unableTime = json_encode($data['unableTime']);
        $coupon->status     = 0;
        $coupon->save();
        $coupon->couponImg = picturePath($coupon->couponImg);
        return $coupon;
    }

    public static function setCoupon(int $id, array $data): void
    {
        $query = CouponModel::query()->find($id);
        if (!$query) {
            throw new CouponException(CouponCodeEnum::ERR_COUPON_ID_NOT_EXIST);
        }

        $s = CouponModel::setData($id, $data);
        if (!$s) {
            throw new CouponException(CouponCodeEnum::ERR_COUPON_DB_SET);
        }
    }

    public static function delCoupon(int $id): void
    {
        $query = CouponModel::query()->find($id);
        if (!$query) {
            throw new CouponException(CouponCodeEnum::ERR_COUPON_ID_NOT_EXIST);
        }

        $s = CouponModel::delData($id);
        if (!$s) {
            throw new CouponException(CouponCodeEnum::ERR_COUPON_DB_DEL);
        }
    }

    public static function patchCouponStatus(int $id, int $status)
    {
        $query = CouponModel::query()->find($id);
        if (!$query) {
            throw new CouponException(CouponCodeEnum::ERR_COUPON_ID_NOT_EXIST);
        }

        $s = CouponModel::setStatus($id, $status);
        if (!$s) {
            throw new CouponException(CouponCodeEnum::ERR_COUPON_DB_PATCH);
        }
    }

    /**
     * 获取门店可用优惠券列表
     * @param $brandId
     * @param $shopId
     * @param $productList
     * @param $usedCouponList
     * @param $source
     * @return PosEnableCouponService|bool
     */
    public static function getPosEnableCouponList($brandId, $shopId, $productList, $usedCouponList, $source)
    {
        //查询传递过来的优惠券信息
        $couponIds           = array_column($usedCouponList, 'couponId');
        $usedCouponList      = [];
        $canUseCouponService = new PosEnableCouponService($brandId, $shopId, $productList,
            $usedCouponList, $source, ActivityEnum::TYPE_POS_ACTIVITY);
        if (count($couponIds) > 0) {
            return $canUseCouponService->checkUsedCoupon($couponIds);
        } else {
            return $canUseCouponService->initPosCoupon();
        }

    }

    /**
     * 数据转换
     * @param $shopRel
     * @param $couponList
     * @return array
     */
    public static function dateToChange($shopRel, $couponList)
    {
        $canUsedCouponList = [];
        $i                 = 0;
        foreach ($couponList as $item => $value) {
            foreach ($value['coupon_rel_by_activity'] as $v) {
                $canUsedCouponList[$i]               = $v;
                $canUsedCouponList[$i]['couponId']   = $v['id'];
                $canUsedCouponList[$i]['shopType']   = $value['shopType'];
                $canUsedCouponList[$i]['activityId'] = $item;
                if (isset($shopRel[$item])) {
                    $canUsedCouponList[$i]['shopRel'] = $shopRel[$item]['activity_shop_rel'];
                }
                $i++;
            }
        }
        return $canUsedCouponList;
    }

    /**
     * 门店下所有的活动优惠券，按活动分类
     * @param int $shopId
     * @return Builder[]|Collection|\Illuminate\Support\Collection
     */
    public static function couponIdsInShop(int $shopId)
    {
        $brandId = ShopService::getShopInfo($shopId)->brandId ?? 0;

        return ActivityService::getActivityIdsByShopId($shopId, ActivityEnum::TYPE_POS_ACTIVITY, $brandId)
                              ->map(function ($item) {
                                  $couponIds = [];
                                  foreach ($item->activityCouponRel as $v) {
                                      $couponIds[] = $v['couponId'];
                                  }

                                  return ['actName' => $item->name, 'couponIds' => $couponIds];
                              });
    }

    public static function getCouponListByIds($couponIds, $field)
    {
        return CouponModel::query()
                          ->whereIn('id', $couponIds)
                          ->select($field)
                          ->get()
                          ->toArray();
    }


    /**
     * 优惠券编辑
     *
     * @param object $params
     */
    public static function update(object $params)
    {
        CouponModel::query()->where("id", $params->id)->update((array)$params);
    }

    /**
     * 查询夸父券信息
     *
     * @param string $couponCode
     * @return array
     * @throws CouponException
     */
    public function getKfCouponInfo(string $couponCode): array
    {
        $couponList = new EnableCouponService($this->brandId, $this->shopId);
        $couponList->setNeedCheckCouponListByCodes([$couponCode]);
        $couponList->checkPosCouponInfo();

        if (!empty($couponList->getUnableList())) {
            $list = $couponList->getUnableList();
            $info = reset($list);
            $msg  = $info['errCause'];
            throw new CouponException(CouponCodeEnum::ERR_POS_CHECK_COUPON_ERROR, $msg);
        }

        if (empty($couponList->getEnableList())) {
            throw new CouponException(CouponCodeEnum::ERR_POS_CHECK_COUPON_ERROR,
                '优惠券不存在, 请检查后再试, 或联系门店运营人员');
        }

        $list = $couponList->getEnableList();
        $info = reset($list);

        if (empty($info['canUseProduct'])) {
            $canUseProducts = null;
        } else {
            $canUseProducts = [
                'isRepeat'    => false, // 是否可以重复
                'selectLimit' => 1, // n 选 1,
                'list'        => [
                    [
                        "canUseProduct" => $info['canUseProduct'],
                        "productLimit"  => 1
                    ]
                ]
            ];
        }

        $result                 = CouponExtBase::formatPrepareResponseData(
            1,
            1,
            '',
            $info['name'],
            $info['couponCode'],
            $info['couponType'],
            (int)$info['costPrice'],
            (int)$info['discount'],
            $info['startAt'],
            $info['endAt'],
            CouponExtEnum::EXT_PLATFORM_KUAFU,
            [],
            $info['canUseProduct'],
            '',
            $canUseProducts
        );
        $result['couponStatus'] = $info['status'];
        return $result;
    }
}
